#include <iostream>
#include <typeinfo>
#include <functional>

using namespace std;

void show()
{
    cout << endl;
}

template<class T, class ...Args>
void show(const T& x, Args ...arg)
{
    cout << x << ' ';
    show(arg...);
}


void test1()
{
   string s("hello linux");
   show(10, 'a', s);
}

//template<class T>
//int showtt(const T& x)
//{
//    cout << x << ' ';
//    return 0;
//}   
//
//template<class ...Args>
//void showt(Args... arg)
//{
//    int a[] = { showt(arg)... };
//}
//
//void test2()
//{
//    string s("helloworld");
//    showt(10, 20, 30, 40, 50, 60, 70, 80, 90, 100);
//}
//
//

namespace Abnormal
{
    class Exceptional
    {
    public:
        Exceptional()
            :_s("Exceptional")
             ,_id(0)
        {}

        virtual const string& what() const
        {
            return _s;
        }

        virtual string gets()
        {
            return _s;
        }
    
    protected:
        string _s;
        int _id;
    };

    class InternetExpl : public Exceptional
    {
    public:
        
        InternetExpl()
            :_in("InternetExpl")
             ,_idinter(1)
        {}

        virtual const string& what() const
        {
            return _in;
        }

        string gets()
        {
            return _in;
        }

    protected:
        string _in;
        int _idinter;
    };
}   

void test(string& s)
{
    if (s != "error")
    {
        cout << s << endl;
    }
    else 
    {
        throw string("is error, to false!!!");
    }
}

void testExceptional(string& s)
{
    Abnormal::Exceptional e;
    Abnormal::InternetExpl i;
    if (e.gets() == s)
    {
        throw e;
    }
    else if (i.gets() == s)
    {
        throw i;
    }
    else 
    {
        cout << "is true == == == == == == == !!!" << endl;
    }
}

template<class T, class K>
void funcAll(T x, K y)
{
    static int count = 0;
    ++ count;
    cout << count << ':' << &count << endl;
}

int func1(int a, int b)
{
    return a + b;
}

class func2
{
public:
    int operator()(int a, int b)
    {
        return a + b;
    }
};

void test()
{
    int a = 10;
    funcAll(func1, a);
    funcAll(func2(), a);
    funcAll([](int x, int y){ return x + y; }, a);

    cout << endl;

    function<int(int, int)> f1 = func1;
    funcAll(f1, a);

    function<int(int, int)> f2 = func2();
    funcAll(f2, a);

    function<int(int, int)> f3 = [](int x, int y){ return x + y; };
    funcAll(f3, a);
}

void print(int a, int b)
{
    cout << a << ':' << b << endl;
}

void bindtest()
{
    int a = 10, b = 20;
    auto func1 = bind(print, placeholders::_1, placeholders::_2);
    auto func2 = bind(print, placeholders::_2, placeholders::_1);
    func1(a, b);
    cout << endl;
    func2(a, b);
}

int main()
{

    bindtest();

    //test();
//    string s;
//    while (cin >> s)
//    {
//        try 
//        {
//            testExceptional(s);
//        }
//        catch (const Abnormal::Exceptional& e)
//        {
//            cout << e.what() << endl;
//        }
//    }

//    string s;
//    while (cin >> s)
//    {
//        try 
//        {
//            test(s);
//        }
//        catch(const string& str)
//        {
//            cout << str << endl;
//        }
//    }




    //test1();
    
    //test2();

//    int a = 10;
//    decltype(a) x = 20;
//    cout << 'a' << ':' << a << "   " << 'x' << ':' << x << endl;
//    cout << typeid(a).name() << ':' << typeid(x).name() << endl;

   // int x = 10, y = 20;
   // cout << x << ':' << y << endl;
   // auto swap = [](int& x, int& y){ int tmp = x; x = y; y = tmp; };
   // swap(x, y);
   // cout << x << ':' << y << endl;

    return 0;
}
